package com.rtsapp.server.utils.collections;

/**
 *
 */
public class LongList {

    private static final int DEFAULT_INIT_LEN = 10;

    //最大长度
    private final int maxLen;

    //数组
    private  long[] arr;

    //可用长度
    private  int validLength = 0 ;

    public LongList(int initLen, int maxLen) {
        if( initLen < 0 || maxLen < 0 || initLen > maxLen ){
            throw new IllegalArgumentException( "非法初始长度或者最大长度" );
        }

        this.maxLen = maxLen;

        arr = new long[ initLen ];
        validLength = 0;
    }

    public long[] arr(){
        return arr;
    }

    /**
     * 长度
     * @return
     */
    public int size(){
        return validLength;
    }

    /**
     * 是否是空的
     * @return
     */
    public boolean isEmpty(){
        return validLength == 0;
    }


    /**
     * 是否已经满了, 不能再加入元素啦
     * @return
     */
    public boolean isFull(){
        return validLength == maxLen;
    }


    /**
     * 加入元素到末尾
     * @param value
     * @throws IndexOutOfBoundsException 数组已经满了
     */
    public void add( long value ){
        add( validLength, value );
    }


    /**
     * 加入元素到指定位置, 原本该位置以及后面的元素都会后移
     * @param index
     * @param value
     * @throws IndexOutOfBoundsException
     */
    public void add( int index, long value ){

        //1. 如果已经满了, 报错
        if( isFull() ){
            throw new IndexOutOfBoundsException( "元素已满, 总元素个数:" + validLength );
        }

        //2. index不能跳跃
        if( index > validLength  ){
            throw new IndexOutOfBoundsException( "索引越界: index=" + index );
        }

        //3. 检查容量
        checkCapacity( );

        //4. 如果index是已有的索引中，后移index以及后面的元素
        if( index < validLength ){
            System.arraycopy( arr, index, arr, index + 1, validLength - index );
        }

        //5. 设置index元素, 并++长度
        arr[ index ] = value;
        validLength++;

    }

    /**
     * 设置某一个位置的值
     * @param index
     * @param value
     * @return 返回原本该位置的值
     * @throws IndexOutOfBoundsException
     */
    public long set( int index, long value ){

        if( index < 0 || index >= validLength ){
            throw new IndexOutOfBoundsException( "索引越界: index=" + index  );
        }

        long  oldValue = arr[ index ];
        arr[ index ] = value;
        return oldValue;
    }


    /**
     * 从前往后移除第一个相等的元素
     * @param value
     */
    public void remove( long value ){
        int index = indexOf( value );
        if( index >= 0 ){

            validLength--;

            if( index < validLength  ){
                System.arraycopy( arr, index +1, arr, index, validLength - index );
            }

        }
    }

    /**
     * 使用下标移除对应的元素
     * @param index
     */
    public void removeByIndex( int index ) {

        removeByIndex( index, 1 );

//        if( index < 0 || index >= validLength ){
//            throw new IndexOutOfBoundsException( "索引越界: index=" + index  );
//        }
//
//        validLength--;
//        System.arraycopy( arr, index +1, arr, index, validLength - index );

    }


    /**
     * 使用下标移除, 指定个数的元素
     * @param index
     */
    public int removeByIndex( int index, int len ){

        if( index < 0 || index >= validLength ){
            throw new IndexOutOfBoundsException( "索引越界: index=" + index  );
        }

        if( len < 1 ){
           return 0;
        }

        len = Math.min( len, size() - index );

        validLength -= len;
        System.arraycopy( arr, index +len, arr, index, validLength - index );

        return len;
    }

    /**
     * 获得指定位置的元素
     * @param index
     * @return
     * @throws IndexOutOfBoundsException
     */
    public long get( int index ){
        if( index < 0 || index >= validLength ){
            throw new IndexOutOfBoundsException( "索引越界: index=" + index  );
        }

        return arr[ index ];
    }


    /**
     * 是否包含指定的元素
     * @param value
     * @return
     */
    public boolean contains( long value ){
        return indexOf( value ) >= 0;
    }


    /**
     * 从前往后元素出现的索引
     * @param value
     * @return <0 表示没有出现
     */
    public int indexOf( long value ){
        for( int i = 0; i < validLength ; ++i ){
            if( arr[ i ] == value ){
                return i;
            }
        }
        return -1;
    }

    /**
     * 从后往前元素出现的索引
     * @param value
     * @return <0 表示没有出现
     */
    public int lastIndexOf( long value ){

        for( int  i = validLength - 1; i >= 0 ; --i ){
            if( arr[ i ] == value ){
                return i;
            }
        }
        return -1;
    }


    private void checkCapacity(){

        if( validLength == arr.length && validLength < maxLen ){

            //如果长度==0, 新长度取10
            int newLen;
            if( validLength == 0 ){
                newLen = ( DEFAULT_INIT_LEN < maxLen ) ? DEFAULT_INIT_LEN : maxLen;
            }else{
                newLen =  ( (validLength * 2) < maxLen ) ? (validLength * 2 ) : maxLen;
            }

            long[] newArr = new long[ newLen ];
            System.arraycopy( arr, 0, newArr, 0, arr.length );

            arr = newArr;
        }

    }

    public void clear() {
        validLength = 0;
    }

}
